﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;

namespace CodeSmithWpf;

public static class StringUtil
{
    /// <summary>
    /// 单词变成单数形式
    /// </summary>
    /// <param name="word"></param>
    /// <returns></returns>
    public static string ToSingular(string word)
    {
        Regex plural1 = new Regex("(?<keep>[^aeiou])ies$");
        Regex plural2 = new Regex("(?<keep>[aeiou]y)s$");
        Regex plural3 = new Regex("(?<keep>[sxzh])es$");
        Regex plural4 = new Regex("(?<keep>[^sxzhyu])s$");

        if (plural1.IsMatch(word))
            return plural1.Replace(word, "${keep}y");
        else if (plural2.IsMatch(word))
            return plural2.Replace(word, "${keep}");
        else if (plural3.IsMatch(word))
            return plural3.Replace(word, "${keep}");
        else if (plural4.IsMatch(word))
            return plural4.Replace(word, "${keep}");

        return word;
    }
    /// <summary>
    /// 单词变成复数形式
    /// </summary>
    /// <param name="word"></param>
    /// <returns></returns>
    public static string ToPlural(string word)
    {
        Regex plural1 = new Regex("(?<keep>[^aeiou])y$");
        Regex plural2 = new Regex("(?<keep>[aeiou]y)$");
        Regex plural3 = new Regex("(?<keep>[sxzh])$");
        Regex plural4 = new Regex("(?<keep>[^sxzhy])$");

        if (plural1.IsMatch(word))
            return plural1.Replace(word, "${keep}ies");
        else if (plural2.IsMatch(word))
            return plural2.Replace(word, "${keep}s");
        else if (plural3.IsMatch(word))
            return plural3.Replace(word, "${keep}es");
        else if (plural4.IsMatch(word))
            return plural4.Replace(word, "${keep}s");

        return word;
    }

    public static string GetUnderlineCase(string value)
    {
        if (value.IsNullOrWhiteSpace())
        {
            return value;
        }
        string result = string.Empty;
        for (int i = 0; i < value.Length; i++)
        {
         
            if (char.IsUpper(value[i]))
            {
                if (i < value.Length - 1)
                {
                   if(!char.IsUpper(value[i + 1]))
                    {
                        if (result.Length > 0)
                        {
                            result += "_";
                        }
                      
                        result += value[i];
                    }
                    else
                    {
                        result += value[i];
                    }
                }
                else
                {
                    result += value[i];
                }
            }
            else
            {
                if (i < value.Length - 1)
                {
                    if (char.IsUpper(value[i + 1]))
                    {
                      
                        result += value[i];
                        result += "_";
                    }
                    else
                    {
                        result += value[i];
                    }
                }
                else
                {
                    result += value[i];
                }
                    
            }
        }
        return result.Replace("__","_").ToLower();
    }
}
public class TypeDTO: INotifyPropertyChanged
{


    /// <summary>
    /// 类注释
    /// </summary>
    public string ClassDescription { get; set; }

    /// <summary>
    /// 实体类型
    /// </summary>
    public Type ClassType { get; set; }
    /// <summary>
    /// 属性
    /// </summary>
    public List<PropertyDTO> Properties { get; set; } = new List<PropertyDTO>();
    /// <summary>
    /// 生成代码路径
    /// </summary>
    public string GeneratePath { get; internal set; }
    /// <summary>
    /// 模块名称
    /// </summary>
    public string ModuleName { get; internal set; }
    /// <summary>
    /// 项目名称
    /// </summary>
    public string ProjectName { get; internal set; }
    /// <summary>
    /// 单位名称
    /// </summary>
    public string CompanyName { get; internal set; }
    private bool @checked;
    /// <summary>
    /// 是否选择
    /// </summary>
    public bool Checked
    {
        get
        {
            return this.@checked;
        }
        set
        {
            this.@checked = value;
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Checked"));
            }
        }
    }
    public string ClassName { get; internal set; }
    public string ClassFullName { get; internal set; }
    public string TableName { get; internal set; }
    public string CodeClassName { get; internal set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public string GetNamespace(string layerName)
    {
        List<string> list = new List<string>();
        if (!this.CompanyName.IsNullOrWhiteSpace())
        {
            list.Add(this.CompanyName);
        }
        if (!this.ProjectName.IsNullOrWhiteSpace())
        {
            list.Add(this.ProjectName);
        }
        if (!layerName.IsNullOrWhiteSpace())
        {
            list.Add(layerName);
        }
       
        return String.Join(".", list);
    }


    public string GetTypeScriptIdTypeValue()
    {
        var property = this.ClassType.GetProperty("Id", BindingFlags.Instance | BindingFlags.Public);
        if (property.PropertyType.IsNullableType())
        {
            return "null";
        }
        string value = property.PropertyType.GetTypeScriptTypeName();
        if (value == "boolean")
        {
            return "false";
        }
        else if (value == "number")
        {
            return "0";
        }
        return "''";
    }
    public string GetTypeScriptIdTypeName()
    {
        var property = this.ClassType.GetProperties().FirstOrDefault(x => x.Name == "Id");
        if (property == null)
        {
            return "string";
        }
        return property.PropertyType.GetTypeScriptTypeName();
    }

    public string GetIdTypeName()
    {
       var property= this.ClassType.GetProperties().FirstOrDefault(x=>x.Name=="Id");
        if(property == null)
        {
            return "string";
        }
        return GetPropertyTypeName(property.PropertyType);
    }

    protected string GetPropertyTypeName(Type type)
    {
        if (type.IsNullableType())
        {
            return type.GetNulllableType().Name + "?";
        }
        return type.Name;
    }


    public string GetApplicationInterfaceClassName()
    {
        return "I"+ GetClassName() + "AppService";
    }

    public string GetApplicationServiceClassName()
    {
        return "" + GetClassName() + "AppService";
    }

    public string GetDtoClassName()
    {
        return GetClassName() + "Dto";
    }

    public string GetCreateOrUpdateDtoClassName()
    {
        return "CreateOrUpdate" + GetClassName() + "Dto";
    }

    public string GetQueryDtoClassName()
    {
        return "Get" + GetClassName() + "InputDto";
    }

    public string GetControllerClassName()
    {
        return "" + GetClassName() + "Controller";
    }

    public string GetTableName()
    {
        return this.ModuleName + "_" + GetClassName();
    }

    public string GetClassPluralPropertyName()
    {
        return StringUtil.ToPlural(GetClassName());
    }

    public string GetTypeScriptName()
    {
      return  System.Text.Json.JsonNamingPolicy.CamelCase.ConvertName(GetClassName());
      
    }

    public string GetTypeScriptFileName()
    {
        return GetClassName();
    }

    public string GetTypeScriptIndexPageName()
    {
        return this.GetClassName() + "ListPage";
    }

    public string GetTypeScriptFormComponentName()
    {
        return GetClassName() + "Form";
    }

    public string GetClassName()
    {
        if (ClassType.Name.EndsWith("Entity"))
        {
            return ClassType.Name.Substring(0, ClassType.Name.Length - 6);
        }
        return this.ClassType.Name;
    }
}

public static class TypeExtenssion
{
    public static bool IsNullableType(this Type type)
    {
        return Nullable.GetUnderlyingType(type) != null;
    }

    public static Type GetNulllableType(this Type type)
    {
        return Nullable.GetUnderlyingType(type);
    }

    public static string GetTypeScriptTypeName(this Type type)
    {
        switch (type.Name)
        {
            case "Float":
            case "Single":
            case "Decimal":
            case "Double":
            case "Int16":
            case "Int32":
            case "Int64":
                return "number";
            case "Boolean":
                return "boolean";
            default:
                return "string";
        }
    }
}
